/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "PWM_LED.h"
#include "semphr.h"
#include "task.h"
#include "queue.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for Task_PWM_LED */
osThreadId_t Task_PWM_LEDHandle;
const osThreadAttr_t Task_PWM_LED_attributes = {
  .name = "Task_PWM_LED",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_Printf */
osThreadId_t Task_PrintfHandle;
const osThreadAttr_t Task_Printf_attributes = {
  .name = "Task_Printf",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for Task_OLED_Show */
osThreadId_t Task_OLED_ShowHandle;
const osThreadAttr_t Task_OLED_Show_attributes = {
  .name = "Task_OLED_Show",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for Task_OLED_Draw */
osThreadId_t Task_OLED_DrawHandle;
const osThreadAttr_t Task_OLED_Draw_attributes = {
  .name = "Task_OLED_Draw",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for TaskDebounce */
osThreadId_t TaskDebounceHandle;
const osThreadAttr_t TaskDebounce_attributes = {
  .name = "TaskDebounce",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for TaskDebounce02 */
osThreadId_t TaskDebounce02Handle;
const osThreadAttr_t TaskDebounce02_attributes = {
  .name = "TaskDebounce02",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for BinSemBright01 */
osSemaphoreId_t BinSemBright01Handle;
const osSemaphoreAttr_t BinSemBright01_attributes = {
  .name = "BinSemBright01"
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void APPTask_PWM_LED(void *argument);
void APPTask_Printf(void *argument);
void APPTask_OLED_Show(void *argument);
void APPTask_OLED_Draw(void *argument);
void APPTaskDebounce(void *argument);
void APPTaskDebounce02(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* creation of BinSemBright01 */
  BinSemBright01Handle = osSemaphoreNew(1, 0, &BinSemBright01_attributes);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of Task_PWM_LED */
  Task_PWM_LEDHandle = osThreadNew(APPTask_PWM_LED, NULL, &Task_PWM_LED_attributes);

  /* creation of Task_Printf */
  Task_PrintfHandle = osThreadNew(APPTask_Printf, NULL, &Task_Printf_attributes);

  /* creation of Task_OLED_Show */
  Task_OLED_ShowHandle = osThreadNew(APPTask_OLED_Show, NULL, &Task_OLED_Show_attributes);

  /* creation of Task_OLED_Draw */
  Task_OLED_DrawHandle = osThreadNew(APPTask_OLED_Draw, NULL, &Task_OLED_Draw_attributes);

  /* creation of TaskDebounce */
  TaskDebounceHandle = osThreadNew(APPTaskDebounce, NULL, &TaskDebounce_attributes);

  /* creation of TaskDebounce02 */
  TaskDebounce02Handle = osThreadNew(APPTaskDebounce02, NULL, &TaskDebounce02_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_APPTask_PWM_LED */
/**
  * @brief  Function implementing the Task_PWM_LED thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_APPTask_PWM_LED */
void APPTask_PWM_LED(void *argument)
{
  /* USER CODE BEGIN APPTask_PWM_LED */
  /* Infinite loop */
  for(;;)
  {
	BaseType_t err=xSemaphoreTake(BinSemBright01Handle,portMAX_DELAY);
	if(err== pdFALSE){
		printf("semaphore was blank");
	}
	else{
		LED_adjust_brightness(hled1);
		printf("Task_pwm:%d",hled1.Brightness);
	}
    vTaskDelay(10);
  }
  /* USER CODE END APPTask_PWM_LED */
}

/* USER CODE BEGIN Header_APPTask_Printf */
/**
* @brief Function implementing the Task_Printf thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTask_Printf */
void APPTask_Printf(void *argument)
{
  /* USER CODE BEGIN APPTask_Printf */
  /* Infinite loop */
  for(;;)
  {
	switch(hled1.Brightness){
			case Dim:
				printf("NOW_brightness:Dim");
				break;
			case LOW:
				printf("NOW_brightness:LOW");
				break;
			case MODERATE:
				printf("NOW_brightness:MODERATE");
				break;
			case HIGH:
				printf("NOW_brightness:HIGH");
				break;
			case VERY_HIGH:
				printf("NOW_brightness:VERY_HIGH");
				break;
			default:
				break;
	}
    osDelay(pdMS_TO_TICKS(100));
  }
  /* USER CODE END APPTask_Printf */
}

/* USER CODE BEGIN Header_APPTask_OLED_Show */
/**
* @brief Function implementing the Task_OLED_Show thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTask_OLED_Show */
void APPTask_OLED_Show(void *argument)
{
  /* USER CODE BEGIN APPTask_OLED_Show */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END APPTask_OLED_Show */
}

/* USER CODE BEGIN Header_APPTask_OLED_Draw */
/**
* @brief Function implementing the Task_OLED_Draw thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTask_OLED_Draw */
void APPTask_OLED_Draw(void *argument)
{
  /* USER CODE BEGIN APPTask_OLED_Draw */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END APPTask_OLED_Draw */
}

/* USER CODE BEGIN Header_APPTaskDebounce */
/**
* @brief Function implementing the TaskDebounce thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTaskDebounce */
void APPTaskDebounce(void *argument)
{
  /* USER CODE BEGIN APPTaskDebounce */
	  uint32_t ulNotificationValue01;
  /* Infinite loop */
  for(;;)
  {
        ulNotificationValue01 = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        if (ulNotificationValue01 == 1)
        {
            vTaskDelay(pdMS_TO_TICKS(20)); 

            if (HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin ) == GPIO_PIN_RESET)
            {	
				switch(hled1.Brightness){
					case Dim:
						break;
					case LOW:
						hled1.Brightness = Dim;
						break;
					case MODERATE:
						hled1.Brightness = LOW;
						break;
					case HIGH:
						hled1.Brightness = MODERATE;
						break;
					case VERY_HIGH:
						hled1.Brightness = HIGH;
						break;
					default:
						break;
					
				}
				if(BinSemBright01Handle != NULL){
					BaseType_t err=xSemaphoreGive(BinSemBright01Handle);
					if(err ==pdFALSE){
						printf("SemaphoreGive_wrong");
					}
					printf("Task_Debounce:%d",hled1.Brightness);
				}
            }
        }
		vTaskDelay(pdMS_TO_TICKS(50));
  }
  /* USER CODE END APPTaskDebounce */
}

/* USER CODE BEGIN Header_APPTaskDebounce02 */
/**
* @brief Function implementing the TaskDebounce02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_APPTaskDebounce02 */
void APPTaskDebounce02(void *argument)
{
  /* USER CODE BEGIN APPTaskDebounce02 */
  uint32_t ulNotificationValue02;
  /* Infinite loop */
  for(;;)
  {
        ulNotificationValue02 = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        if (ulNotificationValue02 == 1)
        {
            vTaskDelay(pdMS_TO_TICKS(20)); 

            if (HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin ) == GPIO_PIN_RESET)
            {	
				switch(hled1.Brightness){
					case Dim:
						hled1.Brightness = LOW;
						break;
					case LOW:
						hled1.Brightness = MODERATE;
						break;
					case MODERATE:
						hled1.Brightness = HIGH;
						break;
					case HIGH:
						hled1.Brightness = VERY_HIGH;
						break;
					case VERY_HIGH:
						break;
					default:
						break;
					
				}
				if(BinSemBright01Handle != NULL){
					BaseType_t err=xSemaphoreGive(BinSemBright01Handle);
					if(err ==pdFALSE){
						printf("SemaphoreGive_wrong");
					}
					printf("Task_Debounce2:%d",hled1.Brightness);
				}
            }
        }
		vTaskDelay(pdMS_TO_TICKS(50));
  }
  /* USER CODE END APPTaskDebounce02 */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	if(GPIO_Pin==KEY2_Pin){
		BaseType_t xHigherPriorityTaskWoken =pdFALSE;
		vTaskNotifyGiveFromISR(TaskDebounceHandle,&xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);		
	
	}
	else if(GPIO_Pin == KEY3_Pin){
		BaseType_t xHigherPriorityTaskWoken =pdFALSE;
		vTaskNotifyGiveFromISR(TaskDebounce02Handle,&xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);		
	
	}

}
/* USER CODE END Application */

